﻿/*******************************************************
 * 
 * 作者：胡庆访
 * 创建时间：20100331
 * 说明：延迟加载外键实体 的实现
 * 运行环境：.NET 3.5 SP1
 * 版本号：1.0.0
 * 
 * 历史记录：
 * 创建文件 胡庆访 20100331
 * 添加非泛型版本的基类，添加InheritanceLazyEntityRef 胡庆访 20100925
 * 
*******************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections;

namespace BPM.Entity
{
	/// <summary>
	/// 强类型的ILazyEntityRef(TEntity)
	/// 
	/// 能够把一个通用的ILazyEntityRef转换成强类型的ILazyEntityRef(TEntity)。
	/// </summary>
	/// <typeparam name="TEntity"></typeparam>
	[Serializable]
	internal class TypedLazyEntityRef<TEntity> : ILazyEntityRef<TEntity>
		where TEntity : BaseEntity
	{
		private ILazyEntityRef _innerRef;

		public TypedLazyEntityRef(ILazyEntityRef innerRef)
		{
			if (innerRef == null) throw new ArgumentNullException("innerRef");

			this._innerRef = innerRef;
		}

		#region 一般实现

		public int Id
		{
			get
			{
				return this._innerRef.Id;
			}
			set
			{
				this._innerRef.Id = value;
			}
		}

		public int? NullableId
		{
			get
			{
				return this._innerRef.NullableId;
			}
			set
			{
				this._innerRef.NullableId = value;
			}
		}

		public bool LoadedOrAssigned
		{
			get
			{
				return this._innerRef.LoadedOrAssigned;
			}
		}

		public bool IsEmpty
		{
			get
			{
				return this._innerRef.IsEmpty;
			}
		}

		public void Load(IList list)
		{
			this._innerRef.Load(list);
		}

		BaseEntity ILazyEntityRef.Entity
		{
			get
			{
				return this._innerRef.Entity;
			}
			set
			{
				this._innerRef.Entity = value;
			}
		}

		#endregion

		/// <summary>
		/// 强类型的实体引用
		/// </summary>
		public TEntity Entity
		{
			get
			{
				return this._innerRef.Entity as TEntity;
			}
			set
			{
				this._innerRef.Entity = value;
			}
		}
	}

	/// <summary>
	/// 延迟加载的外键
	/// </summary>
	/// <typeparam name="TEntity"></typeparam>
	[Serializable]
	internal class LazyEntityRef<TEntity> : ILazyEntityRef<TEntity>
		where TEntity : BaseEntity
	{
		private int _id;

		private BaseEntity _owner;

		private TEntity _entity;

		public LazyEntityRef(BaseEntity owner)
		{
            this._id = DEFAULT_VALUE;
			this._owner = owner;
		}

		/// <summary>
		/// 被引用实体的ID
		/// </summary>
		public int Id
		{
			get
			{
				return this._id;
			}
			set
			{
				if (this._id != value)
				{
					this._id = value;

					this._entity = null;
				}
			}
		}

		public int? NullableId
		{
			get
			{
				if (this.IsEmpty)
				{
					return null;
				}
				return this.Id;
			}
			set
			{
                this.Id = value.HasValue ? value.Value : DEFAULT_VALUE;
			}
		}

		/// <summary>
		/// 这个值用于判断是否正在处于设置Entity的状态中。
		/// 
		/// 当在外界设置Entity属性时，如果获取Entity属性，不需要引起延迟加载。
		/// </summary>
		private bool _settingEntity;

		/// <summary>
		/// 如果是第一次获取此属性，并且还没有为它赋值时，会自动根据Id查询出对应的Entity。
		/// </summary>
		public TEntity Entity
		{
			get
			{
				if (this._settingEntity == false && this._entity == null)
				{
					this.LoadEntity();
				}

				return this._entity;
			}
			set
			{
				var oldEntity = this._entity;

				try
				{
					this._settingEntity = true;

					this._entity = value;
					if (value != null)
					{
						this._id = value.Id;
					}
				}
				finally
				{
					this._settingEntity = false;
				}
			}
		}

		public bool IsEmpty
		{
			get
			{
                return this._id.Equals(DEFAULT_VALUE);
			}
		}

		public bool LoadedOrAssigned
		{
			get
			{
				return this._entity != null;
			}
		}

		private void LoadEntity()
		{
			if (this.IsEmpty || !this._owner.EnableLazyLoading) return;

			var p = LazyProviderFactoryHost.Factory.Create(typeof(TEntity));
			this._entity = p.GetById(this._id) as TEntity;
		}

		public void Load(IList list)
		{
			if (!this.IsEmpty)
			{
				//尝试从缓存中读取。
				var fkEntity = list.OfType<TEntity>().FirstOrDefault(e => e.Id == this._id);
				if (fkEntity != null)
				{
					this.Entity = fkEntity;
				}
				else
				{
					//缓存中没有，则从数据层加载
					fkEntity = this.Entity;

					//加载完毕，加入链表。
					if (fkEntity != null &&
						list.IsReadOnly == false && list.IsFixedSize == false
						)
					{
						list.Add(fkEntity);
					}
				}
			}
		}

		public override string ToString()
		{
			if (this.IsEmpty)
			{
				return "Empty";
			}
			if (this.LoadedOrAssigned)
			{
				return this._entity.ToString();
			}
			return "NotLoaded:" + this._id;
		}

		BaseEntity ILazyEntityRef.Entity
		{
			get
			{
				return this.Entity;
			}
			set
			{
				var typedValue = value as TEntity;
				if (value != null && typedValue == null) throw new ArgumentException("请选择准确的类型赋值！");
				this.Entity = typedValue;
			}
		}

        private readonly int DEFAULT_VALUE = -1;
	}
}